const Koa = require('koa')
const app = new Koa()
const views = require('koa-views')
const json = require('koa-json')
const onerror = require('koa-onerror')
const bodyparser = require('koa-bodyparser')
const logger = require('koa-logger')

// 数据库引入
const db = require('./db/mydb');

// 雪花引入
const snowFlake = require("./snowFlake/snowFlake");

// 引入路由
const index = require('./routes/index')
// 教师评价路由（暂时先不写）
// const evaluate = require('./routes/evaluate');
const login = require('./routes/login/login');
// 通知路由，可能数据库还需要创建一个通知表
// const message = require('./routes/message');
// 学生路由
const student = require('./routes/user/student');
// 教师路由
const teacher = require('./routes/user/teacher');
// 年级路由
const grade = require('./routes/information/grade');
// 学院路由
const institute = require('./routes/information/institute');
// 课程路由
const course = require('./routes/information/course');
// 班级路由
const classes = require('./routes/information/class');
// 作业路由
const assginment = require('./routes/assignment/assignment');
// 用户路由
const user = require('./routes/user/user');
// 小组路由
const group = require('./routes/group/group');

// 仪表板路由
const dashboard = require('./routes/dashboard/dashboard');
// 引入上传文件
const upload = require("./uploadFiles/uploadFiles");

// 时间格式转换引入
const formTime = require('./formTime/formTime');


// 解决跨域问题
const cors = require('koa2-cors');

// 生成token
const jwt = require('jsonwebtoken');
const koaJwt = require('koa-jwt');

const secretKey = "maitoukugan"

const crypto = require('crypto');

// 加密/解密方法引入
const Rsa = require('./Rsa/Rsa');

// 加密/解密方法引入
const Aes = require('./Ase/Ase');


// 定义全局变量
app.context.config = {
  secretKey
};

// error handler
onerror(app)

// middlewares
app.use(bodyparser({
  enableTypes: ['json', 'form', 'text']
}))
app.use(json())
app.use(logger())
app.use(require('koa-static')(__dirname + '/public'))

app.use(views(__dirname + '/views', {
  extension: 'ejs'
}))

// logger
app.use(async (ctx, next) => {
  const start = new Date()
  await next()
  const ms = new Date() - start
  console.log(`${ctx.method} ${ctx.url} - ${ms}ms`)
})

// db
app.use(async (ctx, next) => {
  ctx.db = db;
  await next();
})

// 引入formDate
app.use(async (ctx, next) => {
  ctx.formTime = formTime;
  await next();
})

// 将rsa的秘钥对和aes的秘钥和向量都存储在ctx中
app.use(async (ctx, next) => {
  let sql = "select * from secretKey"
  let sql1 = "select * from aessecret"
  // 生成加密密钥
  let aesKey = crypto.randomBytes(32);
  // 生成向量
  let iv = crypto.randomBytes(16);

  console.log("执行了一次");

  console.log(aesKey, "密钥");
  console.log(iv, "向量");
  
  let res = await ctx.db.EXCUTE(sql, []);
  let res1 = await ctx.db.EXCUTE(sql1, []);
  console.log(res1);
  ctx.state.publicKey = res[0].public_key;
  ctx.state.privateKey = res[0].private_key;
  console.log(res1[0].aesKey, res1[0].iv,'数据库中存储数据');
  ctx.state.aesKey = Buffer.from(res1[0].aesKey, 'utf8');
  ctx.state.iv = Buffer.from(res1[0].iv, "utf8"); 
  // ctx.state.aesKey = res1[0]
  await next();
});

// 引入雪花ID
app.use(async (ctx, next) => {
  ctx.snowFlake = snowFlake;
  await next();
})

// 引入rsa
app.use(async (ctx, next) => {
  ctx.Rsa = Rsa;
  await next();
})

// 引入ASE
app.use(async (ctx, next) => {
  ctx.Aes = Aes;
  await next();
})

// 引入上传=文件的方法
app.use(async (ctx, next) => {
  ctx.upload = upload;
  await next();
})

// 这个cors 必须要写在routes前面，否则就会报错
// 解决跨域问题必须要放在token解析之前，如果 koa-cors 中间件被错误地放置在 koa-jwt 中间件之后，可能会导致 koa-jwt 中间件无法正确解析 Authorization 请求头，从而导致无法正确验证 JWT 认证令牌
// 解决跨域
app.use(cors({
  credentials: true
}));


// 配置 koa-jwt 中间件，验证 token 的合法性, ctx.state.user , 
app.use(koaJwt({ secret: secretKey }).unless({
  // 设置排除检测 token 的路径
  path: [/^\/login/, /^\/register/, /^\/image/]
}));

// 处理请求的中间件
app.use(async (ctx, next) => {
  try {
    await next();
  } catch (err) {
    console.log(err);
    if (err.status === 401) {
      ctx.status = 401;
      ctx.set('X-Auth-Expired', 'true');
      ctx.body = {
        error: 'Invalid token'
      };
    } else {
      throw err;
    }
  }
});


// routes
app.use(index.routes(), index.allowedMethods())
app.use(classes.routes(), classes.allowedMethods())
app.use(student.routes(), student.allowedMethods())
app.use(login.routes(), login.allowedMethods())
app.use(teacher.routes(), teacher.allowedMethods())
app.use(course.routes(), course.allowedMethods())
app.use(grade.routes(), grade.allowedMethods())
app.use(institute.routes(), institute.allowedMethods())
app.use(assginment.routes(), assginment.allowedMethods())
app.use(user.routes(), user.allowedMethods())
app.use(group.routes(), group.allowedMethods())
app.use(dashboard.routes(),dashboard.allowedMethods())

// error-handling
app.on('error', (err, ctx) => {
  console.error('server error', err, ctx)
});



module.exports = app
